﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using elibrary.Classes;
using elibrary.Models.Managers;

namespace elibrary.Models.Entities
{
    public class Notice
    {
        /* Class Fields [Start] ----------------------------------------------------------------- */
        [Key]
        public int id { get; set; }
        public DateTime dateAdded { get; set; }
        public NoticeType type { get; set; }
        public bool enabled { get; set; }
        public string message { get; set; }
        public int userId { get; set; }
        public int associatedId { get; set; }
        /* Class Fields [End] ------------------------------------------------------------------- */

        /* Computed Fields [Start] -------------------------------------------------------------- */
        [NotMapped]
        public User user
        {
            get { return this.getNotifiedUser(this.userId); }
            set { this.userId = value.id; }
        }
        /* Computed Fields [End] ---------------------------------------------------------------- */

        /* Class Enums [Start] ------------------------------------------------------------------ */
        public enum NoticeType
        {
            Others = 0, CartExpired = 100, OrderConfirmed = 101,
            OrderCancelled = 102, PaymentRejected = 103, PaymentApproved = 104, BookSold = 201,
            BookApproved = 202, BookUploadImage = 203, BookReturned = 204, UpdateProfile = 301
        }
        /* Class Enums [End] -------------------------------------------------------------------- */

        private User getNotifiedUser(int uid)
        {
            UserManager userManager = new UserManager(AppGlobals.dataContext);

            return userManager.get(uid);
        }

        public static Notice notifyCartExpired(int uid,int oid)
        {
            UserManager userManager = new UserManager(AppGlobals.dataContext);
            UserOrderManager userOrderManager = new UserOrderManager(AppGlobals.dataContext);
            NoticeManager noticeManager = new NoticeManager(AppGlobals.dataContext);

            User user = userManager.get(uid);
            UserOrder order = userOrderManager.get(oid);

            if (user == null || order == null)
                return null;

            string msg = "Your shopping cart that was created on the " + order.orderDate +
                         " has just expired. All the items added to the previous shopping" +
                         " cart are restored back to the marketplace. Please add them again" +
                         " if you wish to buy those items.";

            return notify(uid,oid,NoticeType.CartExpired,msg);
        }

        public static Notice notifyOrderConfirmed(int uid,int oid)
        {
            UserManager userManager = new UserManager(AppGlobals.dataContext);
            UserOrderManager userOrderManager = new UserOrderManager(AppGlobals.dataContext);
            NoticeManager noticeManager = new NoticeManager(AppGlobals.dataContext);

            User user = userManager.get(uid);
            UserOrder order = userOrderManager.get(oid);

            if (user == null || order == null)
                return null;

            string msg = "Your order with the id:  " + oid + " that was placed on the " +
                         order.orderDate + " has been confirmed. The delivery of" +
                         " the items shall take one to three working days.";

            return notify(uid,oid,NoticeType.OrderConfirmed,msg);
        }

        public static Notice notifyOrderCancelled(int uid,int oid)
        {
            UserManager userManager = new UserManager(AppGlobals.dataContext);
            UserOrderManager userOrderManager = new UserOrderManager(AppGlobals.dataContext);
            NoticeManager noticeManager = new NoticeManager(AppGlobals.dataContext);

            User user = userManager.get(uid);
            UserOrder order = userOrderManager.get(oid);

            if (user == null || order == null)
                return null;

            string msg = "Your order with the id:  " + oid + " that was placed on the " +
                         order.orderDate + " has been cancelled either due to bad payment" +
                         " or other issues. Please contact the admin for more informaiton.";

            return notify(uid,oid,NoticeType.OrderCancelled,msg);
        }

        public static Notice notifyPaymentRejected(int uid,int pid)
        {
            UserManager userManager = new UserManager(AppGlobals.dataContext);
            PaymentManager paymentManager = new PaymentManager(AppGlobals.dataContext);
            NoticeManager noticeManager = new NoticeManager(AppGlobals.dataContext);

            User user = userManager.get(uid);
            Payment payment = paymentManager.get(pid);

            if (user == null || payment == null)
                return null;

            string msg = "Your payment with the id: " + pid + " that was made for the order" +
                         " with id: " + payment.orderId + " that was paid on the " +
                         payment.paymentDate + " has been rejected either due to bad payment" +
                         " details or other issues. Please contact the admin for more informaiton.";

            return notify(uid,pid,NoticeType.PaymentRejected,msg);
        }

        public static Notice notifyBookSold(int uid,int bid)
        {
            UserManager userManager = new UserManager(AppGlobals.dataContext);
            BookManager bookManager = new BookManager(AppGlobals.dataContext);
            NoticeManager noticeManager = new NoticeManager(AppGlobals.dataContext);

            User user = userManager.get(uid);
            Book book = bookManager.get(bid);

            if (user == null || book == null)
                return null;

            var hasAlready = noticeManager.getActiveNotice(NoticeType.BookSold,bid);
            if (hasAlready != null)
                return hasAlready;

            string msg = "The book with the id " + bid + " that was added on" +
                         book.dateAdded + " has been sold.";

            return notify(uid,bid,NoticeType.BookSold,msg);
        }

        public static Notice notifyBookRemitted(int uid,int bid)
        {
            UserManager userManager = new UserManager(AppGlobals.dataContext);
            BookManager bookManager = new BookManager(AppGlobals.dataContext);
            NoticeManager noticeManager = new NoticeManager(AppGlobals.dataContext);

            User user = userManager.get(uid);
            Book book = bookManager.get(bid);

            if (user == null || book == null)
                return null;

            var hasAlready = noticeManager.getActiveNotice(NoticeType.BookApproved,bid);
            if (hasAlready != null)
            {
                hasAlready.enabled = false;
                AppGlobals.dataContext.SaveChanges();        
            }

            return hasAlready;
        }

        public static Notice notifyBookApproved(int uid,int bid)
        {
            UserManager userManager = new UserManager(AppGlobals.dataContext);
            BookManager bookManager = new BookManager(AppGlobals.dataContext);
            NoticeManager noticeManager = new NoticeManager(AppGlobals.dataContext);

            User user = userManager.get(uid);
            Book book = bookManager.get(bid);

            if (user == null || book == null)
                return null;

            var hasAlready = noticeManager.getActiveNotice(NoticeType.BookSold,bid);
            if (hasAlready != null)
                return hasAlready;

            string msg = "The book with the id " + bid + " that was added on" +
                         book.dateAdded + " has been approved.";

            return notify(uid,bid,NoticeType.BookApproved,msg);
        }

        public static Notice notifyBookUploadImg(int uid,int bid)
        {
            UserManager userManager = new UserManager(AppGlobals.dataContext);
            BookManager bookManager = new BookManager(AppGlobals.dataContext);
            NoticeManager noticeManager = new NoticeManager(AppGlobals.dataContext);

            User user = userManager.get(uid);
            Book book = bookManager.get(bid);

            if (user == null || book == null)
                return null;

            var hasAlready = noticeManager.getActiveNotice(NoticeType.BookUploadImage,bid);
            if (hasAlready != null)
                return hasAlready;

            string msg = "The photos for the book with the id " + bid + " that was added on" +
                         book.dateAdded + " has not been uploaded yet. In order for the" +
                         " book to be approved, please upload at least four images.";

            return notify(uid,bid,NoticeType.BookUploadImage,msg);
        }

        public static Notice notifyUpdateProfile(int uid)
        {
            UserManager userManager = new UserManager(AppGlobals.dataContext);
            NoticeManager noticeManager = new NoticeManager(AppGlobals.dataContext);

            User user = userManager.get(uid);

            if (user == null)
                return null;

            var hasAlready = noticeManager.getActiveNotice(NoticeType.UpdateProfile,uid);
            if (hasAlready != null)
                return hasAlready;

            string msg = "Your profile has not been updated yet since registration. Please" +
                         " update your profile before purchasing or selling any books on" +
                         " this website. Your profile can be updated by clicking My Profile" +
                         " in the My Portal menu above.";

            return notify(uid,uid,NoticeType.UpdateProfile,msg);
        }

        public static Notice notify(int uid,int aid,NoticeType ntype,string msg)
        {
            NoticeManager noticeManager = new NoticeManager(AppGlobals.dataContext);

            Notice notice = new Notice { 
                dateAdded = DateTime.Now,
                type = ntype,
                enabled = true,
                message = msg,
                userId = uid,
                associatedId = aid
            };

            noticeManager.add(notice);

            return notice;
        }

        public void disableMe(bool autoSave=true)
        {
            this.enabled = false;

            if (autoSave)
                AppGlobals.dataContext.SaveChanges();
        }
    }
}